package dao

import (
	"fmt"

	"gorm.io/gorm"
	"openeuler.org/PilotGo/PilotGo-plugin-automation/internal/global"
	"openeuler.org/PilotGo/PilotGo-plugin-automation/internal/module/common/enum/script"
	"openeuler.org/PilotGo/PilotGo-plugin-automation/internal/module/script_library/model"
	"openeuler.org/PilotGo/PilotGo-plugin-automation/pkg/utils"
)

func GetScriptVersions(scriptId string) ([]model.ScriptVersion, error) {
	var scriptVersions []model.ScriptVersion
	if err := global.App.MySQL.Model(&model.ScriptVersion{}).Where("script_id = ?", scriptId).Order("id DESC").Find(&scriptVersions).Error; err != nil {
		return []model.ScriptVersion{}, err
	}
	return scriptVersions, nil
}

func AddScriptVersion(sv *model.ScriptVersion) error {
	return global.App.MySQL.Transaction(func(tx *gorm.DB) error {
		if err := tx.Create(sv).Error; err != nil {
			return err
		}
		return nil
	})
}

func UpdateScriptVersion(id int, scriptId string, sv *model.ScriptVersion) error {
	return global.App.MySQL.Transaction(func(tx *gorm.DB) error {
		if err := tx.Model(&model.ScriptVersion{}).Where("id = ? AND script_id = ?", id, scriptId).Updates(sv).Error; err != nil {
			return err
		}
		return nil
	})
}

func DeleteScriptVersion(id int, scriptId string) error {
	return global.App.MySQL.Transaction(func(tx *gorm.DB) error {
		if err := tx.Where("id = ? AND script_id = ?", id, scriptId).Delete(&model.ScriptVersion{}).Error; err != nil {
			return err
		}

		var count int64
		if err := tx.Model(&model.ScriptVersion{}).Where("script_id = ?", scriptId).Count(&count).Error; err != nil {
			return err
		}

		if count == 0 {
			if err := tx.Where("id = ?", scriptId).Delete(&model.Script{}).Error; err != nil {
				return err
			}
		}

		return nil
	})
}

func PublishScriptVersion(id int, scriptId string, newStatus string) error {
	return global.App.MySQL.Transaction(func(tx *gorm.DB) error {
		if newStatus == script.Published.String() {
			if err := tx.Model(&model.ScriptVersion{}).Where("script_id = ?", scriptId).Update("status", script.Develop).Error; err != nil {
				return err
			}
		}

		if err := tx.Model(&model.ScriptVersion{}).Where("id = ? AND script_id = ?", id, scriptId).Update("status", script.ParseScriptPublishStatus(newStatus)).Error; err != nil {
			return err
		}

		var scriptVersion model.ScriptVersion
		if err := tx.Model(&model.ScriptVersion{}).
			Where("id = ? AND script_id = ?", id, scriptId).
			Find(&scriptVersion).Error; err != nil {
			return err
		}

		if err := tx.Model(&model.Script{}).Where("id = ?", scriptId).Update("version_online", scriptVersion.Version).Error; err != nil {
			return err
		}

		return nil
	})
}

func GetLatestScriptVersion(scriptId string) (string, error) {
	var sv model.ScriptVersion
	if err := global.App.MySQL.Model(&model.ScriptVersion{}).Where("script_id = ?", scriptId).Order("id DESC").First(&sv).Error; err != nil {
		return "", err
	}
	return sv.Version, nil
}

func GetPublishedScriptContentByScriptId(scriptId string) (int, string, string, error) {
	var sv model.ScriptVersion
	if err := global.App.MySQL.Model(&model.ScriptVersion{}).Where("script_id = ? AND status = ?", scriptId, script.Published).Find(&sv).Error; err != nil {
		return 0, "", "", err
	}
	return sv.ID, sv.Version, sv.Content, nil
}

func GetPublishedScriptByScriptId(scriptId string) (string, string, string, error) {
	var result struct {
		ScriptType int
		TagNameEn  string
		Content    string
	}

	query := `
	SELECT 
		s.script_type AS script_type,
		t.en_name AS tag_name_en,
		sv.content AS content
	FROM script s
	LEFT JOIN tag t ON t.name = s.tag
	LEFT JOIN script_version sv ON sv.script_id = s.id
	WHERE s.id = ? AND sv.status = ?
	`

	err := global.App.MySQL.Raw(query, scriptId, script.Published).Scan(&result).Error
	if err != nil {
		return "", "", "", fmt.Errorf("查询脚本信息失败: %v", err)
	}
	return script.ScriptTypeMap[result.ScriptType], result.TagNameEn, utils.EncodeScriptContent(result.Content), nil
}
